Skip to content
created by Aha00aAha00a at 2026-06-09
last modified by Aha00aAha00a at 2026-08-24
revision: 3

Dev Telegram

1. 개요

페이지 수정·삭제·rename·파일 첨부 등 콘텐츠를 변경하는 모든 액션이 발생하면 지정한 Telegram 채팅방으로 알림을 보내는 기능.

2. 설정

2.1. 전역 설정 (관리자)

application.conf (또는 wiki.aha00a.com.conf 등 환경별 conf) 의 AhaWiki.telegram 블록에 Bot Token과 Chat ID를 입력한다. 모든 사이트의 변경 이벤트를 수신한다.

AhaWiki {
    telegram {
        botToken: "1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ"
        chatId: "123456789"
    }
}
  • botToken@BotFather에서 발급받은 Bot Token (전역 공유, 사이트별 설정 없음)
  • chatId — 전체 관리자가 수신할 Chat ID (문자열; 개인은 양수, 그룹·채널은 음수)
  • botToken이 비어있으면 전체 알림 비활성화

2.2. 사이트별 설정 (사이트 관리자)

DB의 Config 테이블에 키 Telegram.chatId로 해당 사이트의 Chat ID를 저장하면, 해당 사이트의 이벤트를 전역 chatId와 함께 사이트별 chatId에도 추가로 전송한다. 같은 Bot Token을 사용한다.

  • Admin UI: /Admin/Site/:seq/Config → **Telegram** 카드에서 Chat ID 입력 후 Save
  • 전역 chatId와 사이트별 chatId가 동일하면 중복 전송하지 않음 (.distinct 처리)
  • 사이트별 chatId만 설정하고 전역 chatId를 비워도 동작함

2.3. Chat ID 확인 방법

  • Bot과 대화를 시작하거나 채널/그룹에 Bot을 초대한 뒤 메시지를 한 번 전송
  • https://api.telegram.org/bot{BOT_TOKEN}/getUpdates 를 호출하여 chat.id 값을 확인

3. 알림 이벤트 및 메시지 형식

이벤트

이모지

메시지 예시

페이지 신규 생성

🆕

🆕 **PageName** created by 닉네임\n코멘트(있을 때만)\nURL

페이지 수정

✏️

✏️ **PageName** r5 edited by 닉네임\n코멘트(있을 때만)\ndiff URL

페이지 삭제

🗑️

🗑️ **PageName** deleted by 닉네임\nURL

마지막 리비전 삭제

⏪ **PageName** r5 revision deleted by 닉네임\nURL

페이지 rename

📝

📝 **OldName** → **NewName** renamed by 닉네임\nURL

파일 첨부 업로드

📎

📎 **PageName** filename.pdf attached by 닉네임\nURL

파일 첨부 삭제

🗑️📎

🗑️📎 **PageName** filename.pdf attachment deleted by 닉네임\nURL

클립보드 이미지 붙여넣기

🖼️

🖼️ **PageName** image pasted by 닉네임\nURL

Google Spreadsheet 동기화

🔄

🔄 **PageName** spreadsheet synced by 닉네임\nURL

  • 페이지명은 HTML bold (<b>)로 강조, parse_mode=HTML 사용
  • 페이지명·닉네임·파일명 등 동적 값은 HTML 특수문자(&, <, >) 이스케이프 처리
  • 모든 알림은 disable_notification: true 로 전송 (무음)
  • 페이지 수정 이벤트의 URL은 해당 리비전의 diff 링크 (?action=diff&after=r번호), 나머지는 페이지 직접 링크

4. 구현

  • app/logics/ApplicationConf.scalaAhaWiki.telegram.botToken() / chatId() 설정 읽기
  • app/models/tables/Config.scalaConfig.Query.Telegram.chatId() / saveChatId() 캡슐화
    • DB 키: Telegram.chatId
    • chatId() — 읽기 (Option[String], 미설정 시 None)
    • saveChatId(v) — 쓰기 (비우면 자동 삭제)
  • app/logics/TelegramLogic.scala — 알림 전송 전담 클래스 (@Singleton, DI)
    • sendTo(chatId, message) — 단일 chatId로 Telegram API 호출 (비동기 fire-and-forget)
    • send(message, siteChatId) — 전역 chatId + 사이트별 chatId를 deduplicate하여 sendTo 호출
    • pageUrl / diffUrl / h / b / commentLine — 내부 유틸 (diffUrlpageUrl + ?action=diff&after=revision)
    • 이벤트별 public 메서드 — 모두 siteChatId: Option[String] = None 파라미터 보유
  • app/controllers/Wiki.scala
    • TelegramLogic 주입
    • siteTelegramChatId(implicit connection, site)Config.Query.Telegram.chatId()로 사이트별 chatId 조회
    • 각 액션 핸들러(save, delete, deleteLastRevision, rename, uploadAttachment, deleteAttachment, uploadClipboardImage, syncGoogleSpreadsheet)에서 성공 시 siteTelegramChatId를 함께 전달
  • app/controllers/Diary.scala
    • TelegramLogic 주입
    • write 핸들러: 신규 페이지면 notifyPageCreated, 기존 페이지 append면 notifyPageEdited 호출
  • app/controllers/Api.scala
    • GET /api/Admin/Site/:seq/Telegram — chatId 조회
    • PUT /api/Admin/Site/:seq/Telegram — chatId 저장 (Config.Query.Telegram.saveChatId)

4.1. 비동기 처리

wsClient.url(...).post(...).foreach(...) 방식으로 결과를 기다리지 않으므로, Telegram API 지연·오류가 페이지 저장 응답에 영향을 주지 않는다. 전송 실패 시 logger.warn 으로만 기록한다.

5. See Also

5.2. Similar Pages

Similar pages by cosine similarity. Words after page name are term frequency.

  • Same Wiki
    • 33.12% Dev WebSocket page(12:42), id(23:25), 페이지(9:20), url(13:5), name(10:8), save(5:13), wiki(5:13), 처리(4:14), 저장(2:12), site(8:5)
  • Sister Wikis
    • 47.55% Aha00a:Telegram chat(35:6), telegram(22:15), id(23:4), bot(10:5), url(13:1), name(10:2), app(6:4), api(6:2), token(5:2), org(1:6)

5.3. Adjacent Pages

Control
≤ 32
all
1.0x
1.0x
80
-120
ON
Metrics
Nodes(visible/total)0/0
Links(visible/total)0/0
Avg degree0.00
Depth coverage0
Queue(fetch/graph)0 / 0
Zoom(scale)1.00x
Ctrl/⌘ + Scroll: Zoom
Root 1-hop 2-hop+